home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / TTFHDX / SCSI.STT < prev    next >
Encoding:
Text File  |  2001-02-09  |  17.4 KB  |  665 lines

  1. ;+
  2. ; Edit History
  3. ;
  4. ; May-17-89    ml.    Started this with jwt's SCSI code.
  5. ; Aug-21-89    ml.    Added format code.
  6. ; Nov-17-89    ml.    Only add 8 to byte count on DMA reads, not writes.
  7. ; Dec-04-89    ml.    Always hand-shake last 8 bytes of data when writing
  8. ;            to disk because of hardware counter handling.
  9. ;            Added w4cntout().
  10. ;            (refer to comments at _wrtscsi())
  11. ; Jan-23-90    ml.    Undid modifications done on Dec-04-89.
  12. ;            (refer to comments at _wrtscsi())
  13. ; Jul-31-90    ml.    Modified to handle vectored-interrupts in addition
  14. ;            to polling.
  15. ;-
  16.  
  17.  
  18. .include    "defs.h"
  19. .include    "sysvar.h"
  20. .include    "scsi.h"
  21.  
  22. ;+
  23. ; Command length
  24. ;-
  25. NCMD    equ    6        ; length of short command (in bytes)
  26.  
  27.  
  28. .if    VI            ; if vectored-interrupts desired
  29. dmac_int:    dc.b    0    ; flag for DMAC interrupts
  30. phase_changed:    dc.b    0    ; flag for SCSI phase changes
  31. .endif    ;VI
  32.  
  33.  
  34. .if    !DRIVER            ; not to be included in driver
  35. scxltmout:    dc.l    12001    ; SCSI extra long-timeout (>= 1 min)
  36. slwsclto:    dc.l    5000    ; SCSI long-timeout (25 S) for stunit()
  37. slwscsto:    dc.l    42    ; SCSI short-timeout (205 mS) for stunit()
  38. scltmout:    dc.l    201    ; SCSI long-timeout (at least 1000 ms)
  39. scstmout:    dc.l    101    ; SCSI short-timeout (at least 500 ms)
  40. .even
  41. .endif    ;!DRIVER
  42.  
  43.  
  44. ;+
  45. ; smplscsi() - send a simple SCSI command (ie. no DMA involved)
  46. ;
  47. ;    d0.w = physical unit number
  48. ;    d1.l = transfer length (in bytes)
  49. ;    d2.w = command length (NCMD or LCMD)
  50. ;    a0.l = buffer address
  51. ;-
  52.     .globl    _smplscsi
  53. _smplscsi:
  54.     andi.w    #7,d0            ; mask off the flags to get unit num
  55.     bsr    sblkscsi        ; send command block
  56.     bpl.s    .0            ; if successful, wait for status
  57.     rts                ; else return
  58. .0:    bra    w4stat            ; waiting for status byte
  59.  
  60.  
  61. ;+
  62. ; rcvscsi() - send a SCSI command which receives data back.
  63. ;
  64. ; Passed:
  65. ;    d0.w = physical unit number
  66. ;    d1.l = transfer length (in bytes)
  67. ;    d2.w = command length (NCMD or LCMD)
  68. ;    a0.l = buffer address
  69. ;
  70. ; Comments:
  71. ;    The code that checks whether there is data left in the residue
  72. ; register does not work for some transfers of less than 4 bytes to a
  73. ; non-longword aligned address.  
  74. ;-
  75.     .globl    _rcvscsi
  76. _rcvscsi:
  77. .if    !SCDMA                ; if not doing DMA
  78.     move.l    a0,-(sp)        ; save buffer address
  79. .endif    ;SCDMA
  80.     andi.w    #7,d0            ; mask off the flags to get unit num
  81.  
  82. .if    SCDMA                ; if doing DMA
  83. .if    ODMA                ; and using Old DMA controller
  84.     addq.l    #8,d1            ; add 8 because of hardware bug
  85. .endif    ;ODMA
  86. .endif    ;SCDMA
  87.  
  88.     move.w    d2,-(sp)        ; save the command length
  89.     bsr    sblkscsi        ; send command block
  90.     move.w    (sp)+,d2        ; restore the command length
  91. .if    !SCDMA                ; if not doing DMA
  92.     move.l    (sp)+,a0        ; restore buffer address
  93. .endif    ;SCDMA
  94.     tst.w    d0            ; successful?
  95.     bmi.s    rsend            ; if not successful, return
  96.  
  97.     move.b    #0,SCSIICR        ; deassert the data bus
  98.     move.b    #1,SCSITCR        ; set data in phase
  99.     move.b    SCSIREI,d0        ; clear potential interrupt
  100.  
  101. .if    SCDMA
  102.                     ; Set up the DMAC for data transfer
  103.     move.b    #2,SCSIMR        ; enable DMA mode
  104.     move.b    #0,SCSIDIR        ; start the DMA receive
  105.     move.w    #DMAIN,SDMACTL        ; set the DMAC direction to IN
  106.     move.w    #DMAIN+DMAENA,SDMACTL    ; turn on DMAC
  107.  
  108.     bsr    setscstmout        ; set up a short timeout
  109.     cmpi.w    #NCMD,d2        ; is this a long command?
  110.     beq.s    .0            ; if not, just go on
  111.     bsr    setscxltmout        ; else, set up an extra long timeout
  112. .0:    bsr    w4int            ; wait for interrupts
  113.     tst.w    d0            ; successful?
  114.     bne.s    rsend            ; if error, returns
  115.     bsr    w4stat            ; wait for status byte
  116.     tst.w    d0            ; successful?
  117.     bne.s    rsend            ; if error, returns
  118.     move.l    d0,-(sp)        ; else save returned status
  119.  
  120.     move.b    bSDMAPTR+6,d0        ; see if this was an odd transfer
  121.     andi.w    #3,d0            ; (ie, not multiple of 4)
  122.     beq.s    .2            ; no, nice and even (and easy)
  123.  
  124.     movea.l    #bSDMAPTR,a1        ; a1 -> DMA address
  125.     movep.l    (0,a1),d0        ; d0 = current value of DMA pointer
  126.     move.l    d0,d1            ; d1 = current value of DMA pointer
  127.  
  128.     andi.w    #3,d0            ; # bytes left in residue register
  129.     andi.w    #$FFFF-3,d1        ; where does data go to?
  130.     movea.l    d1,a0            ; a0 -> where rest of data should go
  131.     move.l    SDMARES,d1        ; get the residue
  132.     subq.w    #1,d0            ; dbra likes one less than count
  133. .1:    rol.l    #8,d1            ; tranfer residue to buffer
  134.     move.b    d1,(a0)+
  135.     dbra    d0,.1
  136.  
  137. .2:    move.l    (sp)+,d0        ; recall the status byte
  138.  
  139. .else    ;SCDMA
  140.     movea.l    a0,a1            ; a1 -> buffer to read into
  141.     movea.l    #bSCSI,a2        ; a2 -> 5380
  142. .3:    bsr    setscstmout
  143.     bsr    w4req            ; wait for REQ to come
  144.     bmi.s    rsend            ; if timed out, returns
  145.     btst    #3,5*REGSTEP(a2)    ; still in data in phase?
  146.     beq    w4stat            ; no, go get status
  147.     move.b    (a2),(a1)+        ; read the data byte
  148.     bsr    doack
  149.     bra.s    .3            ; do next byte
  150. .endif    ;SCDMA
  151. rsend:    rts
  152.  
  153.  
  154. ;+
  155. ; wrtscsi() - send a SCSI command which will write data to the target
  156. ;
  157. ; Passed:
  158. ;    d0.w = physical unit number
  159. ;    d1.l = transfer length (in bytes)
  160. ;    d2.w = command length (NCMD or LCMD)
  161. ;    a0.l = buffer address
  162. ;
  163. ; Comments: 
  164. ; 12/04/89 ml
  165. ;    Bus error occurs when doing a write to the disk that ends at top
  166. ; of memory.  The DMA counter is decremented when the bytes are written 
  167. ; from the ping pong buffers to the device, not when bytes are grapped 
  168. ; from RAM to the ping pong buffers.  Well, AFTER the last 8 bytes are 
  169. ; read into the ping pong buffers and BEFORE they are written to the 
  170. ; device, the chip will attempt to read the NEXT 8 bytes into the ping 
  171. ; pong buffers which results in a bus error because it will be reading 
  172. ; pass top of memory.  To get around this HARDWARE BUG, the code will 
  173. ; ALWAYS handshake the last 8 bytes over instead of DMAing them.
  174. ;
  175. ; 01/23/90 ml
  176. ;    A. Pratt said he's willing to move the screen down and sacrifice
  177. ; 16 bytes of memory.  So, code added on 12/04/89 is commented out.
  178. ;-
  179.     .globl    _wrtscsi
  180. _wrtscsi:
  181.     andi.w    #7,d0            ; mask off the flags to get unit num
  182.  
  183. .if    !SCDMA
  184.     move.l    a0,-(sp)        ; save beginning buffer address
  185. .endif    ;!SCDMA
  186.  
  187. .0:    move.w    d2,-(sp)        ; save command length
  188.     bsr    sblkscsi        ; send command block
  189.     move.w    (sp)+,d2        ; restore command length
  190. .if    !SCDMA
  191.     move.l    (sp)+,a0        ; a0 = where DMA ends
  192. .endif    ;!SCDMA
  193.     tst.w    d0            ; successful?
  194.     bpl.s    .1            ; if successful, go on
  195.     rts                ; else return
  196.  
  197. .1:    move.b    #0,SCSITCR        ; set data out phase
  198.     move.b    SCSIREI,d0        ; clear potential interrupt
  199.  
  200. .if    SCDMA
  201.                     ; Set up the DMAC for data transfer
  202.     move.b    #2,SCSIMR        ; enable DMA mode
  203.     move.b    #0,SCSIDS        ; start the DMA send
  204.     move.w    #DMAOUT,SDMACTL        ; set the DMAC direction
  205.     move.w    #DMAOUT+DMAENA,SDMACTL    ; turn on DMAC
  206.  
  207.     bsr    setscstmout        ; set up a short timeout
  208.     cmpi.w    #NCMD,d2        ; is this a long command?
  209.     beq.s    .2            ; if not, just go on
  210.     bsr    setscxltmout        ; set up an extra long timeout
  211. .2:    bsr    w4int            ; wait for interrupts
  212.     tst.w    d0
  213.     bne.s    wsend            ; if failed, return
  214.     bsr    w4stat            ; wait for status byte
  215.  
  216. .else    ;SCDMA
  217.                     ; hand shake the rest over the bus
  218.     movea.l    a0,a1            ; a1 -> buffer to write from
  219.     movea.l    #bSCSI,a2        ; a2 -> 5380
  220. .3:    bsr    setscstmout
  221.     bsr    w4req            ; wait for REQ to come
  222.     bmi.s    wsend            ; if timed out, returns
  223.     btst    #3,5*REGSTEP(a2)    ; still in data out phase?
  224.     beq    w4stat            ; no, go get status
  225.     move.b    (a1)+,(a2)        ; write the data byte
  226.     bsr    doack
  227.     bra.s    .3            ; do next byte
  228. .endif    ;SCDMA
  229. wsend:    rts
  230.  
  231.  
  232.  
  233. ;+
  234. ; sblkscsi() - set DMA pointer and count and send command block
  235. ;
  236. ; Passed:
  237. ;    d0.w = physical unit number
  238. ;    d1.l = transfer length (in bytes)
  239. ;    d2.w = command length (NCMD or LCMD)
  240. ;    a0.l = buffer address
  241. ;
  242. ; Returns:
  243. ;    d0.l =  0 if successful
  244. ;    d0.l = -1 if timeout
  245. ;-
  246.     .extern    _cmdblk
  247. sblkscsi:
  248.     movem.l    d1-d2/a0,-(sp)        ; preserve d1, d2 and a0
  249.     move.w    d0,-(sp)        ; physical unit #
  250.     bsr    selscsi            ; select the unit
  251.     addq.l    #2,sp            ; clean up stack
  252.     movem.l    (sp)+,d1-d2/a0        ; restore d1, d2 and a0
  253.     tst.w    d0            ; selection successful?
  254.     bmi.s    sbsend            ; if timed out, return
  255.                     ; else proceed
  256. .if    SCDMA
  257.     move.l    a0,d0            ; d0 = buffer address
  258.     movea.l    #bSDMAPTR,a1        ; a1 -> DMA address
  259.     movep.l    d0,(0,a1)        ; set DMA pointer
  260.  
  261.     movea.l    #bSDMACNT,a1        ; a1 -> DMA count
  262.     movep.l    d1,(0,a1)        ; set DMA count
  263. .endif    ;SCDMA
  264.  
  265.     move.b    #2,SCSITCR        ; assert C/D
  266.     move.b    #1,SCSIICR        ; assert data bus
  267.  
  268.     bsr    setscstmout        ; set up timeout for sending cmdblk
  269.     lea    _cmdblk,a1        ; a1 -> command block
  270.     subq.w    #1,d2            ; dbra likes one less
  271. .0:    move.b    (a1)+,d0        ; d0.b = byte to be sent
  272.     bsr    hshake            ; write that byte
  273.     tst.w    d0
  274.     bmi.s    sbsend            ; if timed-out, returns
  275.     dbra    d2,.0            ; until whole command block is sent
  276.     moveq    #0,d0            ; all operations successful
  277. sbsend: rts                ; heading home
  278.  
  279.  
  280. ;+
  281. ; BOOLEAN selscsi(SCSIUnit) 
  282. ; WORD SCSIUnit;
  283. ;-
  284. selscsi:
  285.     bsr    setscstmout        ; set up a short timeout
  286. .0:    btst    #6,SCSICR        ; STILL busy from last time?
  287.     beq.s    .1            ; if not, it's available
  288.     cmp.l    (a0),d1            ; timeout?
  289.     bhi.s    .0            ; not yet, wait some more
  290.     bra.s    .3            ; else, return error
  291.  
  292. .1:    move.b    #0,SCSITCR        ; data out phase
  293.     move.b    #0,SCSIISR        ; no interrupt from selection
  294.     move.b    #$0c,SCSIICR        ; assert BSY and SEL
  295. ; set dest SCSI IDs
  296.     clr.w    d0
  297.     move.w    4(sp),d1        ; get the SCSI unit desired
  298.     bset    d1,d0            ; set the appropriate bit
  299.     move.b    d0,SCSIODR        ; (real code would set ours too)
  300.  
  301.     move.b    #$0d,SCSIICR        ; assert BUSY, SEL and data bus
  302.     andi.b    #$FE,SCSIMR        ; clear arbitrate bit
  303.     andi.b    #$F7,SCSIICR        ; clear BUSY
  304.     nop                ; 2 deskew delays
  305.     nop
  306.  
  307.     bsr    setscstmout        ; set up for timeout
  308. .2:    btst    #6,SCSICR        ; wait for bus to be busy
  309.     bne.s    .4
  310.     cmp.l    (a0),d1
  311.     bhi.s    .2
  312.  
  313. .3:    moveq    #-1,d0            ; time out
  314.     bra.s    .5
  315.     
  316. .4:    clr.w    d0            ; selection successful
  317. .5:    move.b    #$0,SCSIICR        ; clear SEL and data bus assertion
  318.     rts
  319.  
  320.  
  321. *+
  322. * VOID resetscsi();
  323. *-
  324.     .globl    resetscsi
  325. resetscsi:
  326.     move.b    #$80,SCSIICR    ; assert RST
  327.     bsr    setscstmout    ; wait (at least) 250 ms
  328. .0:    cmp.l    (a0),d1
  329.     bhi.s    .0
  330.     move.b    #$00,SCSIICR
  331.     bsr    setscltmout    ; wait (at least) 1000 ms
  332. .1:    cmp.l    (a0),d1
  333.     bhi.s    .1
  334.     rts
  335.  
  336.  
  337. ;+
  338. ; w4int - wait for interrupts from 5380 or DMAC during DMA tranfers
  339. ;
  340. ; Passed:
  341. ;    d1.l = expiration time
  342. ;    a0.l = address of _hz_200
  343. ;
  344. ; Returns:
  345. ;    d0.l = returned status or timeout error
  346. ;
  347. ; Comments:
  348. ;    When 5380 is interrupted, it indicates a change of data to
  349. ; status phase (i.e., DMA is done), or ...
  350. ;    When DMAC is interrupted, it indicates either DMA count is
  351. ; zero, or there is an internal bus error.
  352. ;-
  353. w4int:    
  354. .0:    
  355. .if    VI
  356.     tst.b    phase_changed        ; phase changed?
  357. .else    ;VI
  358.     btst    #GPIP2SCSI,GPIP2    ; wait for 5380 to interrupt
  359. .endif    ;VI
  360.  
  361.     bne.s    .3            ; active HIGH
  362.     cmp.l    (a0),d1            ; time's up yet?
  363.     bls.s    .4            ; if not, wait some more
  364.  
  365. .if    VI
  366.     tst.b    dmac_int        ; DMAC interrupted?
  367.     bne.s    .1            ; if so, check out why
  368. .else    ;VI
  369.     btst    #5,GPIP2        ; or for DMAC to interrupt
  370.     beq.s    .1            ; active LOW
  371. .endif    ;VI
  372.  
  373.     cmp.l    (a0),d1            ; time's up yet?
  374.     bhi.s    .0            ; if not, wait some more
  375.                     ; timed-out
  376. .4:    bsr    resetscsi        ; reset the SCSI bus
  377.     moveq    #-1,d0            ; else, return timeout
  378.     bra.s    w4iend
  379.  
  380. .1:    move.w    SDMACTL,d0        ; get the DMAC status
  381.     andi.l    #$80,d0            ; check for bus err/ignore cntout ints
  382.  
  383. .if    VI
  384.     bne.s    .2            ; if bus error reset bus
  385.     sf    dmac_int        ; else clear dmac interrupt flag
  386.     bra.s    .0            ; and wait some more
  387. .else    ;VI
  388.     beq.s    .0            ; if fine, wait for interrupts again
  389. .endif    ;VI
  390.  
  391. .2:    move.w    d0,-(sp)        ; save the returned status
  392.     bsr    resetscsi        ; reset the SCSI bus
  393.     move.w    (sp)+,d0        ; d0 = return code
  394.  
  395. .if    VI
  396.     sf    dmac_int        ; clear dmac interrupt flag
  397. .endif    ;VI
  398.  
  399.     bra.s    w4iend            ; returns
  400. .3:    
  401. .if    VI
  402.     sf.b    phase_changed        ; clear phase change flag
  403.     move.b    SCSICR,d0        ; d0 = SCSI control register
  404.     andi.b    #$1c,d0            ; mask off irrelevant bits
  405.     cmpi.b    #$c,d0            ; data phase -> status phase?
  406.     bne.s    .0            ; if not, wait some more
  407. .endif    ;VI
  408.  
  409.     moveq    #0,d0            ; DMA is successful
  410.     move.b    SCSIREI,d1        ; clear potential interrupt
  411.     move.w    #DMADIS,SDMACTL        ; disable DMA
  412.     move.b    #0,SCSIMR        ; disable DMA mode
  413.     move.b    #0,SCSIICR        ; make sure data bus is not asserted
  414. w4iend:    rts
  415.  
  416.  
  417. ;+
  418. ; w4stat - wait for status byte and message byte.
  419. ;
  420. ; Returns:
  421. ;    d0.l = returned status or timeout error
  422. ;-
  423. w4stat:    bsr    setscstmout        ; set up time-out for REQ and ACK
  424.     move.b    #3,SCSITCR        ; status in phase
  425.     move.b    SCSIREI,d0        ; clear potential interrupt
  426.  
  427.     bsr    w4req            ; wait for status byte
  428.     bmi.s    w4send            ; if timed-out, returns
  429. gstat:    moveq    #0,d0            ; clear d0
  430.     move.b    SCSIDB,d0        ; get the status byte
  431.     move.l    d0,-(sp)        ; save the status byte
  432.     bsr    setscstmout        ; set up time-out for REQ and ACK
  433.     bsr    doack            ; signal that status byte is here
  434.     tst.w    d0            ; timed-out?
  435.     beq.s    .1            ; if not, wait for message byte
  436.  
  437. .0:    addq.l    #4,sp            ; else clean up stack
  438.     bra.s    w4send            ; and return
  439.  
  440. .1:    bsr    setscstmout        ; set up timeout for REQ and ACK
  441.     bsr    w4req            ; wait for message byte
  442.     bmi.s    .0            ; if timed-out, returns
  443.  
  444.     move.b    SCSIDB,d0        ; get and ignore message byte
  445.     bsr    doack            ; signal that message byte is here
  446.     tst.w    d0            ; timed-out?
  447.     bmi.s    .0            ; if so, return timeout
  448.  
  449. .if    DEBUG
  450.     move.l    #_hz_200,a0        ; For debugging SEA177N - 
  451.     moveq    #4,d1            ;   add a delay after receiving 
  452.     add.l    (a0),d1            ;   message byte
  453. .2:    cmp.l    (a0),d1
  454.     bhi.s    .2
  455. .endif    ;DEBUG
  456.  
  457.     move.l    (sp)+,d0        ; recall the status byte
  458. w4send:    rts
  459.  
  460.  
  461. ;+
  462. ; w4req() - wait for REQ to come
  463. ;
  464. ; Passed:
  465. ;    d1.l = expiration time
  466. ;    a0.l = address of _hz_200
  467. ;
  468. ; Returns:
  469. ;     0 - if successful
  470. ;    -1 - times out
  471. ;-
  472. w4req:
  473. .0:    btst    #5,SCSICR        ; waiting for REQ to come
  474.     bne.s    .1            ; if REQ comes, done
  475.     cmp.l    (a0),d1            ; time's up?
  476.     bhi.s    .0            ; if not, wait some more
  477.     moveq    #-1,d0            ; else, returns timed out
  478.     bra.s    w4rend
  479. .1:    moveq    #0,d0            ; returns successful
  480. w4rend:    rts
  481.  
  482.  
  483. ;+
  484. ; doack() - assert ACK
  485. ;
  486. ; Passed:
  487. ;    d1.l = expiration time
  488. ;    a0.l = address of _hz_200
  489. ;
  490. ; Returns:
  491. ;     0 - if successful
  492. ;    -1 - times out
  493. ;-
  494. doack:    ori.b    #$11,SCSIICR        ; assert ACK (and data bus)
  495. .0:    btst    #5,SCSICR        ; wait for REQ to go away
  496.     beq.s    .1            ; if REQ goes away, done
  497.     cmp.l    (a0),d1            ; time's up?
  498.     bhi.s    .0            ; if not, wait some more
  499.     moveq    #-1,d0            ; else returns timed out
  500.     bra.s    doaend
  501. .1:    moveq    #0,d0            ; returns successful
  502. doaend:    andi.b    #$ef,SCSIICR        ; clear ACK
  503.     rts
  504.  
  505.  
  506. ;+
  507. ; hshake() - hand shake a byte over to the controller
  508. ;
  509. ; Passed:
  510. ;    d0.b = byte to be handed over
  511. ;    d1.l = expiration time
  512. ;    a0.l = address of _hz_200
  513. ;
  514. ; Returns:
  515. ;    Whatever w4req() or doack() returns, which is:
  516. ;         0 - if successful
  517. ;        -1 - times out
  518. ;-
  519. hshake:    move.w    d0,-(sp)        ; preserve d0.w
  520.     bsr    w4req            ; wait for REQ to come
  521.     bmi.s    hsend            ; if timed out, returns
  522.     move.b    1(sp),SCSIDB        ; write a byte out to data bus
  523.     bsr    doack            ; assert ACK
  524. hsend:    addq.l    #2,sp            ; clean up stack
  525.     rts
  526.  
  527.  
  528. ;+
  529. ; setscstmout - set up a timeout count for the SCSI for SCSTMOUT long
  530. ;
  531. ; Returns:
  532. ;    a0.l = address of _hz_200 clock
  533. ;    d1.l = expiration time
  534. ;-
  535.  
  536. .if    DRIVER                ; to be included in driver
  537.     .extern    scstmout
  538. .endif    ;DRIVER
  539.  
  540. setscstmout:
  541.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  542.     move.l    scstmout,d1        ; d0 = scstmout _hz_200 clicks
  543.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  544.     rts
  545.  
  546.  
  547. ;+
  548. ; setscltmout - set up a timeout count for the SCSI for SCLTMOUT long
  549. ;
  550. ; Returns:
  551. ;    a0.l = address of _hz_200 clock
  552. ;    d1.l = expiration time
  553. ;-
  554.  
  555. .if    DRIVER                ; to be included in driver
  556.     .extern    scltmout
  557. .endif    ;DRIVER
  558.  
  559. setscltmout:
  560.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  561.     move.l    scltmout,d1        ; d0 = scltmout _hz_200 clicks
  562.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  563.     rts
  564.  
  565.  
  566. ;+
  567. ; setscxltmout - set up a timeout count for the SCSI for SCXLTMOUT long
  568. ;
  569. ; Returns:
  570. ;    a0.l = address of _hz_200 clock
  571. ;    d1.l = expiration time
  572. ;-
  573.  
  574. .if    DRIVER                ; to be included in driver
  575.     .extern    scxltmout
  576. .endif    ;DRIVER
  577.  
  578. setscxltmout:
  579.     movea.l    #_hz_200,a0        ; a0 -> 200 hz clock
  580.     move.l    scxltmout,d1        ; d0 = scltmout _hz_200 clicks
  581.     add.l    (a0),d1            ; d0 = curr time + # clicks to wait
  582.     rts
  583.  
  584.  
  585.  
  586. .if    !DRIVER                ; not to be included in driver
  587.  
  588. ;+
  589. ; fmtscsi() - format a SCSI unit
  590. ;
  591. ;    d0.w = physical unit number
  592. ;    d1.l = transfer length (in bytes)
  593. ;    d2.w = command length (NCMD or LCMD)
  594. ;    a0.l = buffer address
  595. ;-
  596.     .globl    _fmtscsi
  597. _fmtscsi:
  598.     andi.w    #7,d0            ; mask off the flags to get unit num
  599.     bsr    sblkscsi        ; send command block
  600.     bpl.s    .0            ; if successful, wait for status byte
  601.     rts                ; else return
  602. .0:    move.b    #3,SCSITCR        ; status in phase
  603.     move.b    SCSIREI,d0        ; clear potential interrupt
  604. .1:    btst    #5,SCSICR        ; wait forever for REQ to 
  605.  
  606.  
  607. .if    DEBUG
  608.  
  609.     bne.s    .3            ; For debugging purpose - 
  610.     move.l    #_hz_200,a0        ;    add a delay in this "tight" 
  611.     moveq    #2,d1            ;    loop to slow down SCSI chip 
  612.     add.l    (a0),d1            ;    accessing.
  613. .2:    cmp.l    (a0),d1
  614.     bhi.s    .2
  615.     bra.s    .1
  616.  
  617. .else    ;DEBUG
  618.  
  619.     beq.s    .1            ;   come
  620.  
  621. .endif    ;DEBUG
  622.  
  623. .3:    bra    gstat            ; when REQ comes, get status byte
  624.  
  625. .endif    ;!DRIVER
  626.  
  627.  
  628. .if    VI
  629. ;+
  630. ; scsi_isr - interrupt service routine for SCSI phase changes
  631. ;-
  632.     .globl    scsi_isr
  633. scsi_isr:
  634.     movem.l    d0-d1,-(sp)        ; save d0 and d1
  635.     move.b    SCSIDSR,d0        ; read DMA status register
  636.     move.b    d0,d1            ; d0 and d1 contains DMA status
  637.     andi.b    #$10,d0            ; interrupt coming from IRQ
  638.     beq.s    scsiend            ; if not, not interested
  639.     andi.b    #$2c,d1            ; else mask off irrelevant bits
  640.     cmpi.b    #$1f,d1            ; if status > 0x1f
  641.     bhi.s    scsiend            ;   ignore parity error interrupt
  642.     btst.l    #$3,d1            ; phase match bit cleared?
  643.     bne.s    scsiend            ; if not, not interested
  644.                     ; else it's a phase mismatch interrupt
  645.     st    phase_changed        ; set flag to indicate phase changes
  646. scsiend:
  647.     movem.l    (sp)+,d0-d1        ; restore d0 and d1
  648.     move.b    #$7f,ISRA2        ; clear GPIP2SCSI in-service bit
  649.     rte
  650.  
  651.  
  652.  
  653. ;+
  654. ; dmac_isr - interrupt service routine for DMAC
  655. ;    It means we are either a cntout zero or internal bus error.
  656. ;-
  657.     .globl    dmac_isr
  658. dmac_isr:
  659.     st    dmac_int        ; indicate DMAC was interrupted
  660.     move.b    #$7f,ISRB2        ; clear GPIP25 in-service bit 
  661.     rte
  662.  
  663. .endif    ;VI
  664.  
  665.